/*!
 * \file Stage.h
 * \brief Defines a Stage class as stage in the execution plan after parsing the
 *        arguments
 *
 * This file contains the definition for the CLAP :: Stage Class. This is a
 * class to generate a stage to execute given inputs and a set of options and
 * subcommands available.
 */

#ifndef _CLAP_STAGE_H_
#define _CLAP_STAGE_H_

#include "Types.h"
#include "Option.h"

using namespace libCLAP;

namespace libCLAP
{
   namespace CLAP
   {
      class Option;
      /*!
       * \class Stage
       * \brief A class to define a Stage object for a given input.
       *
       * A stage is a step in an ExecutionPlan. A Stage contains switches
       * and also arguments for each step of command execution. A Stage can
       * be thought of as a thinned down subcommand without all the
       * superfluous information, such as Description, etc. A Stage also acts
       * as a doubly linked list node. It has a parent and a next pointer.
       */
      class Stage
      {
         public :

         /*!
          * \brief Constructor
          *
          * Constructor that constructs the object with no arguments or
          * switches.
          *
          * \param name A String that holds the name of the stage.
          */
         Stage ( const Common :: String & name );

         /*!
          * \brief Copy Constructor
          *
          * Constructor that constructs the object as a copy of the parameter
          *
          * \param copy A Stage that holds the stage to be copied.
          */
         Stage ( const Stage & copy );

         /*!
          * \brief Destructor
          */
         virtual ~Stage ( void ) throw ();

         /*!
          * \brief An AddOption function
          *
          * A function to add a switch as a switch of this
          * Stage
          *
          * \param addition A Option object to add as a switch of this
          *                 Stage
          */
         virtual void AddOption ( Option & addition );

         /*!
          * \brief An AddArgument function
          *
          * A function to add an argument as an argument of this
          * Stage. Note that the order is preserved when arguments are
          * encountered, relative to other arguments. This why a queue is
          * used instead of just a vector.
          *
          * \param addition A Common :: String object to add as an argument
          *                 of this stage
          */
         virtual void AddArgument ( Common :: String & addition );

         /*!
          * \brief A Shift function
          *
          * This function is analogous to shift in perl. It shifts the top
          * most part of an array. In this instance, this shifts the
          * Arguments queue. Essentially Shift is a useful alias for top ()
          * and pop () consecutively.
          *
          * \return A Common :: String object that is the next argument in
          *         the list.
          */
         virtual const Common :: String Shift ( void );

         /*!
          * \brief Operator =
          *
          * This operator can be used to set another Stage type to this.
          * parameter Stage type.
          *
          * \param assign This is the Stage to set equal to.
          *
          * \return This Stage
          */
         virtual Stage & operator = ( const Stage & assign );

         /*!
          * \brief Operator ==
          *
          * This operator can be used to check if two Stage objects are equal to
          * eachother.
          *
          * \param compare This is the Stage to check for equality
          *
          * \return A bool that is true if the two Stage objects are equal
          */
         virtual bool operator == ( const Stage & compare ) const;

         /*!
          * \brief Operator !=
          *
          * This operator can be used to check if two Stage objects are inequal to
          * eachother.
          *
          * \param compare This is the Stage to check for inequality
          *
          * \return A bool that is true if the two Stage objects aren't equal
          */
         virtual bool operator != ( const Stage & compare ) const;

         /*!
          * \brief Operator <
          *
          * This operator is used to check if this Stage object is less than the
          * parameter Stage object.
          *
          * \param compare This is the Stage to compare with.
          *
          * \return A bool that is true if this Stage opject is less than the
          *         parameter stage object.
          */
         virtual bool operator < ( const Stage & compare ) const;

         /*!
          * \brief Operator >
          *
          * This operator is used to check if this Stage object is greater than the
          * parameter Stage object.
          *
          * \param compare This is the Stage to compare with.
          *
          * \return A bool that is true if this Stage opject is greater than the
          *         parameter stage object.
          */
         virtual bool operator > ( const Stage & compare ) const;

         /*!
          * \brief Variable Manipulator
          *
          * Standard function to access the class variable.
          */
         virtual map < Common :: String, Option* > & Options ( void );

         /*!
          * \brief Variable Manipulator
          *
          * Standard function to access the class variable.
          */
         virtual const map < Common :: String, Option* > & Options ( void ) const;

         /*!
          * \brief Variable Manipulator
          *
          * Standard function to access the class variable.
          */
         virtual const queue < Common :: String > & Arguments ( void ) const;

         /*!
          * \brief Variable Manipulator
          *
          * Standard function to access the class variable.
          */
         virtual const Common :: String & Name ( void ) const;

         private :

         /*!
          * \brief Variable Manipulator
          *
          * Standard function to access the class variable.
          */
         virtual const queue < Common :: String > & Arguments
               ( const queue < Common :: String > & variable );

         /*!
          * \brief Variable Manipulator
          *
          * Standard function to access the class variable.
          */
         virtual const map < Common :: String, Option* > & Options
               ( const map < Common :: String, Option* > & variable );

         /*!
          * \brief Variable Manipulator
          *
          * Standard function to access the class variable.
          */
         virtual const Common :: String & Name ( Common :: String & variable );

         map < Common :: String, Option* > _Options;
         /*< The map holding the switches that can be associated with the
          *  SubCommand object.*/

         queue < Common :: String > _Arguments;
         /*< The queue holding the arguments that can be associated with the
          *  main CLI object.*/

         Common :: String _Name; /*< The name of the Stage, this should be
                                     the same as the name of the SubCommand
                                     that the stage represents.*/
      };
   }
}
#endif
